﻿namespace EyeSoft.Wpf.Facilities.Collection.Property
{
	using System;
	using System.Collections;
	using System.Collections.Generic;
	using System.Linq;
	using System.Threading.Tasks;

	using EyeSoft.Wpf.Facilities.Collections.ObjectModel;

	internal class CollectionFilled<TService, T, TCollectionType>
		: ICollectionFilled<TCollectionType>
		where TService : IDisposable
	{
		private readonly LoaderParams<TService> loaderParams;

		private readonly SmartObservableCollection<TCollectionType> collection;

		private readonly IComparer comparer;

		private readonly Task task;

		internal CollectionFilled(
			LoaderParams<TService> loaderParams,
			Func<TService, IEnumerable<T>> func,
			SmartObservableCollection<TCollectionType> collection,
			IComparer comparer)
		{
			this.loaderParams = loaderParams;
			this.collection = collection;
			this.comparer = comparer;

			Action action = () => LoadCollection(func);

			if (loaderParams.TaskFactory == null)
			{
				action();
				return;
			}

			task = loaderParams.TaskFactory.StartNew(action);
		}

		public void Completed(Action<SmartObservableCollection<TCollectionType>> action)
		{
			if (task == null)
			{
				action(collection);
				return;
			}

			task.ContinueWith(t => TaskContinue.Execute(() => action(collection)));
		}

		public void Completed<TConverted>(Action<SmartObservableCollection<TConverted>> action)
		{
			var mapper = loaderParams.Mapper;

			var convertedCollection = new SmartObservableCollection<TConverted>();

			convertedCollection.AddRange(collection.Select(x => mapper.Map<TConverted>(x)));

			if (task == null)
			{
				action(convertedCollection);
				return;
			}

			task.ContinueWith(t => TaskContinue.Execute(() => action(convertedCollection)));
		}

		private void LoadCollection(Func<TService, IEnumerable<T>> func)
		{
			var dataService = new DataService<TService>(loaderParams.Mapper, loaderParams.ProxyFactory);

			dataService.LoadEnumerable(func, collection);

			if (collection != null && comparer != null)
			{
				collection.Sort(comparer);
			}
		}
	}
}